// Module: order_send (with packed arrays)
// Description: Compare the bid/askprice with the FV.
//              Send buy or sell orders with the current bid/askprice. 

module order_send #(
  parameter int NUM_CONTRACTS = 3,
  parameter int FV_LAT = 1                              // FV pipeline latency clock cycles
)(
  input  logic clk_net, 
  input  logic rst_n,
  input  logic [NUM_CONTRACTS-1:0][31:0]   fv_all,      // Stored FV values of all apple types passed by fv_calc
  input  logic [NUM_CONTRACTS-1:0][31:0]   bbo_bidprice,
  input  logic [NUM_CONTRACTS-1:0][31:0]   bbo_askprice,
  input  logic [NUM_CONTRACTS-1:0]         bbo_changed,

  output logic [NUM_CONTRACTS-1:0]         send_order_vld,
  output logic [NUM_CONTRACTS-1:0][31:0]   send_order_price,
  output logic [NUM_CONTRACTS-1:0]         send_order_buy
);

  logic [NUM_CONTRACTS-1:0][31:0] bid_q, ask_q;
  logic [NUM_CONTRACTS-1:0] trig_q [0:FV_LAT];
  logic [NUM_CONTRACTS-1:0] bbo_changed_d;

  integer i, d;

  always_ff @(posedge clk_net) begin
    if (!rst_n) begin                           // reset
      bid_q <= 0;
      ask_q <= 0;
      bbo_changed_d <= 0;
      for (d=0; d<=FV_LAT; d++) trig_q[d] <= 0;
      send_order_vld   <= 0;
      send_order_price <= 0;
      send_order_buy   <= 0;

    end else begin
      send_order_vld <= 0;                     // vld signal from last cycle should not affect the new cycle
      bbo_changed_d <= bbo_changed;            
      trig_q[0] <= bbo_changed & ~bbo_changed_d; // trig_q[0] is 1 only at the moment when bbo_changed changes from 0 to 1
      
      for (d = 1; d <= FV_LAT; d++) begin       // delay FV_LAT clock beats
        trig_q[d] <= trig_q[d-1];
      end

      for (i = 0; i < NUM_CONTRACTS; i++) begin
        if (trig_q[0][i]) begin
          bid_q[i] <= bbo_bidprice[i];
          ask_q[i] <= bbo_askprice[i];
        end
      end

      // main buy or sell logic
      if (trig_q[FV_LAT][0]) begin
        for (i = 1; i < NUM_CONTRACTS; i++) begin             // Do not send orders for the main instrument
            if (ask_q[i] < fv_all[i]) begin
              send_order_vld[i]   <= 1'b1;
              send_order_price[i] <= ask_q[i];
              send_order_buy[i]   <= 1'b1;                    // Buy trigger
            end else if (bid_q[i] > fv_all[i]) begin 
              send_order_vld[i]   <= 1'b1;
              send_order_price[i] <= bid_q[i];
              send_order_buy[i]   <= 1'b0;                    // Sell trigger
            end
          end
        end
      end
  end

endmodule


